/*
Copyright 2025 PerfXLab (Beijing) Technologies Co., Ltd.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include "OpenSpB_Global.h"
#include "OpenSpB_Alloc.h"
#include <stdlib.h>

OpenSpB_index OpenSpB_all_object = 0;
OpenSpB_index *OpenSpB_all = &OpenSpB_all_object;

typedef struct
{
    bool is_csc;
    OpenSpB_vector_format_value_ext vector_format;
} OpenSpB_Global_struct;

extern OpenSpB_Global_struct OpenSpB_Global;

OpenSpB_Global_struct OpenSpB_Global = {
    .is_csc = true,
    .vector_format = OpenSpB_dense};

void OpenSpB_Global_is_csc_set(bool is_csc)
{
    OpenSpB_Global.is_csc = is_csc;
}

extern bool OpenSpB_Global_is_csc_get()
{
    return (OpenSpB_Global.is_csc);
}

void OpenSpB_Global_Vector_Format_set(
    OpenSpB_vector_format_value_ext format)
{
    OpenSpB_Global.vector_format = format;
}

extern OpenSpB_vector_format_value_ext OpenSpB_Global_get_Vector_Format()
{
    return (OpenSpB_Global.vector_format);
}

LinkedListMes_t LinkedListMes = {
    .capacity_nnz = 512,
    .capacity_nnz_row = 64,
    .capacity_vector_nnz = 64};

void OpenSpB_LinkedList_malloc()
{
    unsigned int nnz = LinkedListMes.capacity_nnz;
    LinkedListMes.ListNodes = OpenSpB_aligned_malloc(sizeof(listNode) * nnz);

    unsigned int nnz_row = LinkedListMes.capacity_nnz_row;
    LinkedListMes.ListPtr = OpenSpB_aligned_malloc(sizeof(listNode) * nnz_row);
}

void OpenSpB_LinkedList_grow(unsigned int nnz, unsigned int nnz_row)
{
    unsigned int new_capacity = LinkedListMes.capacity_nnz;

    while (nnz > new_capacity)
    {
        new_capacity = ((new_capacity) ? ((new_capacity) << 4) : 1);
    }

    if (new_capacity > LinkedListMes.capacity_nnz)
    {
        LinkedListMes.capacity_nnz = new_capacity;
        LinkedListMes.ListNodes =
            OpenSpB_aligned_realloc(LinkedListMes.ListNodes, sizeof(listNode) * new_capacity);
    }

    new_capacity = LinkedListMes.capacity_nnz_row;
    while (nnz_row > new_capacity)
    {
        new_capacity = ((new_capacity) ? ((new_capacity) << 4) : 1);
    }

    if (new_capacity > LinkedListMes.capacity_nnz_row)
    {
        LinkedListMes.capacity_nnz_row = new_capacity;
        LinkedListMes.ListPtr =
            OpenSpB_aligned_realloc(LinkedListMes.ListPtr, sizeof(listNode *) * new_capacity);
    }
}

void OpenSpB_LinkedList_free()
{
    free(LinkedListMes.ListNodes);
    free(LinkedListMes.ListPtr);
}

void OpenSpB_NNZ_Counting_Mes_malloc()
{
    unsigned int vector_nnz = LinkedListMes.capacity_vector_nnz;
    LinkedListMes.Indices_NZRows = OpenSpB_aligned_malloc(sizeof(unsigned int) * vector_nnz);
    LinkedListMes.LL_Index_Ptr = OpenSpB_aligned_malloc(sizeof(unsigned int) * (vector_nnz + 1));
}

void OpenSpB_NNZ_Counting_Mes_grow(unsigned int nnz)
{
    unsigned int new_capacity = LinkedListMes.capacity_vector_nnz;

    while (nnz > new_capacity)
    {
        // 16 times increase.
        new_capacity = ((new_capacity) ? ((new_capacity) << 4) : 1);
    }

    if (new_capacity > LinkedListMes.capacity_vector_nnz)
    {
        LinkedListMes.capacity_vector_nnz = new_capacity;
        LinkedListMes.Indices_NZRows =
            OpenSpB_aligned_realloc(LinkedListMes.Indices_NZRows, sizeof(unsigned int) * new_capacity);
        LinkedListMes.LL_Index_Ptr =
            OpenSpB_aligned_realloc(LinkedListMes.LL_Index_Ptr, sizeof(unsigned int) * (new_capacity + 1));
    }
}

void OpenSpB_NNZ_Counting_Mes_free()
{
    free(LinkedListMes.Indices_NZRows);
    free(LinkedListMes.LL_Index_Ptr);
}

bool warrning_switch = true;

OpenSpB_info OpenSpB_Warning_switch_set_ext(bool val)
{
    warrning_switch = val;
    return OpenSpB_success;
}

bool OpenSpB_Warning_switch_get()
{
    return warrning_switch;
}